/**
 * @brief 对象池
 * @version 1.0.0
 * @author 宋炜
 * @details 该对象池使用对象池分配器分配内存,对象池分配器使用内存池分配内存.
 *          内存池分配器使用内存池分配内存.
 */

#pragma once

#include <memory>
#include <list>
#include <set>
#include <unordered_set>

#include "misc.hpp"
#include "locker.hpp"
#include "./allocator.hpp"

namespace wheels{
template<typename T , typename Allocator = objPoolAllocator< T >>
class objPool{
public:
    using type_t = T;
    using allocator_t = Allocator;
public:
    /**
     * @brief 构造函数
     * @param allocator 分配器
     */
    template<typename ... Args>
    objPool( int count, Args && ... args ) : m_max_count__( count ){
        if( count <= 0 ){
            throw std::invalid_argument( "count must be greater than 0" );
        }
        pt_pool__ = std::make_shared< memPool< uint8_t >>();
        pt_pool__->registerType( sizeof( type_t ), count );
        m_allocator__.setMemPool( pt_pool__ );

        for( int i = 0; i < count; ++i ){
            auto * ptr = m_allocator__.allocate( sizeof( type_t ) );
            new( ptr ) type_t( std::forward< Args >( args )... );
            m_unsed_list__.push_back( ptr );
        }
    }

    /**
     * @brief 析构函数.定义为虚析构函数以防派生类析构时内存泄漏
     */
    virtual ~objPool(){
        while (m_lock__.test_and_set(std::memory_order_acquire)) {
            std::this_thread::yield();
        }
        for( auto * ptr : m_unsed_list__ ){
            m_allocator__.deallocate( ptr );
        }
        m_lock__.clear(std::memory_order_release);
        clear();
    }
    /**
     * @brief 增加对象数量
     * @param count 对象数量
     * @param args 构造参数
     * @return true 成功
     * @return false 失败
     */
    template<typename ... Args>
    bool incCountTo( int count, Args && ... args ){
        //mutexUniqueLock( lock, m_mutex__ );
        if( count <= 0 ) return false;
        while (m_lock__.test_and_set(std::memory_order_acquire)) {
            std::this_thread::yield();
        }
        
        for( int i = m_unsed_list__.size(); i < count; ++i ){
            auto * ptr = m_allocator__.allocate( sizeof( type_t ) );
            new( ptr ) type_t( std::forward< Args >( args )... );

            m_unsed_list__.push_back( ptr );
        }   
        m_max_count__ = count;
        m_lock__.clear(std::memory_order_release);
        return true;
    }
    /**
     * @brief 减少对象数量
     * @param count 对象数量
     * @return true 成功
     * @return false 失败
     */
    bool decCountTo( int count ){
        if( count <= 0  ) return false;

        while (m_lock__.test_and_set(std::memory_order_acquire)) {
            std::this_thread::yield();
        }
       
        if(m_unsed_list__.size() <= 0){
            m_lock__.clear(std::memory_order_release);
            return false;
        }
        for( size_t i = m_unsed_list__.size(); i > (size_t)count; --i ){    
            if( m_unsed_list__.empty() ){
                m_lock__.clear(std::memory_order_release);
                return false;
            }
            m_unsed_list__.pop_back();
        }
        m_max_count__ = count;
        m_lock__.clear(std::memory_order_release);
        return true;
    }
    /**
     * @brief 收缩内存池大小
     * @return true 成功
     * @return false 失败
     */ 
    bool shrinkToFit(){
        while (m_lock__.test_and_set(std::memory_order_acquire)) {
            std::this_thread::yield();
        }
        m_max_count__ = m_unsed_list__.size();
        pt_pool__->reCount( sizeof( type_t ), m_max_count__ );
        m_lock__.clear(std::memory_order_release);
        return true;
    }
    /**
     * @brief 清空对象池
     */
    void clear(){

        //mutexUniqueLock( lock, m_mutex__ );
        while (m_lock__.test_and_set(std::memory_order_acquire)) {
            std::this_thread::yield();
        }
        m_unsed_list__.clear();
        //m_used_list__.clear();
        m_lock__.clear(std::memory_order_release);
    }

    /**
     * @brief 获取对象
     * @return std::shared_ptr< type_t > 对象指针
     */
    type_t * get(){
        while (m_lock__.test_and_set(std::memory_order_acquire)) {
            std::this_thread::yield();
        }

        if( m_unsed_list__.empty() ){
            m_lock__.clear(std::memory_order_release);
            return nullptr;
        }
        type_t * p = nullptr;

        p = m_unsed_list__.front();
        m_unsed_list__.pop_front();

        m_lock__.clear(std::memory_order_release);
        return p;
    }
    /**
     * @brief 归还对象
     * @param p 对象指针
     */
    void release( type_t * p ){
        while (m_lock__.test_and_set(std::memory_order_acquire)) {
            std::this_thread::yield();
        }

        if( p ){
           m_unsed_list__.push_back( p );
        }
        m_lock__.clear(std::memory_order_release);
    }
protected:
    mutexType_t                             m_mutex__;          // 互斥锁
    std::shared_ptr< memPool< uint8_t >>    pt_pool__;          // 内存池
    allocator_t                             m_allocator__;      // 分配器
    std::list< type_t *>                    m_unsed_list__;     // 未使用对象列表
    int                                     m_max_count__ = 0;  // 最大对象数量
    std::atomic_flag                        m_lock__ = {0};   // 是否正在操作
};
}